package com.gitee.wsl.common.chart.render.background.grid

import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import com.gitee.wsl.common.chart.ChartEnum
import com.gitee.wsl.common.draw.area.Viewport
import com.gitee.wsl.common.chart.render.background.axis.line.CategoryLineAxis
import com.gitee.wsl.common.chart.render.background.axis.line.DataLineAxis
import com.gitee.wsl.common.chart.render.background.axis.model.PlotAxisTick
import com.gitee.wsl.common.ui.draw.type.LineSpacingStyle
import com.gitee.wsl.android.ui.ext.type.drawLine
import com.gitee.wsl.ext.base.ifValue
import com.gitee.wsl.math.Math
import com.gitee.wsl.jvm.math.add
import com.gitee.wsl.jvm.math.div
import com.gitee.wsl.jvm.math.mul
import com.gitee.wsl.jvm.math.sub

class PlotGrid {
    //横向网格线
    val gridLineHorizontalPaint: Paint by lazy {
          Paint().apply {
              isAntiAlias = true
              strokeWidth = 1f
              color = Color.rgb(180, 205, 230)
        }
    }

    //竖向网格线
    val gridLineVerticalPaint: Paint by lazy {
        Paint().apply {
            isAntiAlias = true
            strokeWidth = 1f
            color = Color.rgb(180, 205, 230)
        }
    }

    //是否显示横向网格线
    var isShowHorizontalLines = false

    //是否显示竖向网格线
    var isShowVerticalLines = false

    //是否显示奇数行填充色
    var isShowOddRowBgColor = false

    //是否显示偶数行填充色
    var isShowEvenRowBgColor = false

    //横向网格线
    val oddBgColorPaint: Paint by lazy {
        Paint().apply {
            style = Paint.Style.FILL
            color = Color.WHITE
            isAntiAlias = true
        }
    }

    //竖向网格线
    val evenBgColorPaint: Paint by lazy {
       Paint().apply {
           style = Paint.Style.FILL
           color = Color.rgb(239, 239, 239)
           isAntiAlias = true
        }
    }

    // Solid、Dot、Dash。
    var horizontalLineSpacingStyle = LineSpacingStyle.Solid
    
    var verticalLineSpacingStyle = LineSpacingStyle.Solid

    /**
     * 是否为主Tick对应的网格线,如果是,在划线时需加粗
     * @param primary 是否为主Tick如是则会加粗显示
     */
    var isMajorTickLine = false


    /**
     * 绘制奇数行填充
     * @param left        左边X坐标
     * @param top        顶上Y坐标
     * @param right        右边X坐标
     * @param bottom    底上Y坐标
     */
    private fun drawOddRowsFill(
        canvas: Canvas,
        left: Float, top: Float, right: Float, bottom: Float
    ) {
        if (isShowOddRowBgColor) {
            canvas.drawRect(left, bottom, right, top, oddBgColorPaint)
        }
    }

    /**
     * 绘制偶数行填充
     * @param left        左边X坐标
     * @param top        顶上Y坐标
     * @param right        右边X坐标
     * @param bottom     底上Y坐标
     */
    private fun drawEvenRowsFill(
        canvas: Canvas,
        left: Float, top: Float, right: Float, bottom: Float
    ) {
        if (isShowEvenRowBgColor) {
            canvas.drawRect(left, bottom, right, top, evenBgColorPaint)
        }
    }

    /**
     * 绘制横向网格线
     * @param startX    起始点X坐标
     * @param startY    起始点Y坐标
     * @param stopX        终止点X坐标
     * @param stopY        终止点Y坐标
     */
    private fun drawGridLinesHorizontal(
        canvas: Canvas,
        startX: Float, startY: Float, stopX: Float, stopY: Float
    ) {
        if (this.isShowHorizontalLines) {
            var initWidth = 0.0f
            if (isMajorTickLine) {
                initWidth = gridLineHorizontalPaint.strokeWidth
                gridLineHorizontalPaint.strokeWidth = initWidth + BLOB_WIDTH
            }
            canvas.drawLine(
                horizontalLineSpacingStyle,
                startX, startY, stopX, stopY,
                gridLineHorizontalPaint
            )
            if (isMajorTickLine)
                gridLineHorizontalPaint.strokeWidth = initWidth
        }
    }

    /**
     * 绘制竖向网格线
     * @param startX    起始点X坐标
     * @param startY    起始点Y坐标
     * @param stopX        终止点X坐标
     * @param stopY        终止点Y坐标
     */
    private fun drawGridLinesVertical(
        canvas: Canvas,
        startX: Float, startY: Float, stopX: Float, stopY: Float
    ) {
        if (isShowVerticalLines) {
            var initWidth = 0.0f
            if (isMajorTickLine) //主线
            {
                initWidth = gridLineVerticalPaint.strokeWidth
                gridLineVerticalPaint.strokeWidth = initWidth + BLOB_WIDTH
            }

            //默认是minor
            canvas.drawLine(
                verticalLineSpacingStyle,
                startX, startY, stopX, stopY,
                gridLineVerticalPaint
            )
            if (isMajorTickLine) gridLineVerticalPaint.strokeWidth = initWidth
        }
    }

    fun showHorizontalLines() {
        isShowHorizontalLines = true
    }

    fun showVerticalLines() {
        isShowVerticalLines = true
    }

    fun showEvenRowBgColor() {
       isShowEvenRowBgColor = true
    }

    fun showOddRowBgColor() {
       isShowOddRowBgColor = true
    }


    fun renderHorizontalGridLines(
        canvas: Canvas,
        isMajorTickLine: Boolean,
        plotLeft: Float, plotRight: Float,
        tickID: Int, tickCount: Int,
        ySteps: Float, currentY: Float
    ){
        if (tickID < 0) return  //tickID <= 0

        // 从左到右的横向网格线
        if (tickID > 0) {
            if (tickID % 2 != 0) {
                drawOddRowsFill(canvas, plotLeft, Math.add(currentY, ySteps), plotRight, currentY)
            } else {
                drawEvenRowsFill(canvas, plotLeft, Math.add(currentY, ySteps), plotRight, currentY)
            }
        }
        if (tickID in 0 until tickCount) {
            this.isMajorTickLine = isMajorTickLine
            drawGridLinesHorizontal(canvas, plotLeft, currentY, plotRight, currentY)
        }
    }

    fun renderVerticalGridLines(
        canvas: Canvas, plotTop: Float, plotBottom: Float,
        tickID: Int, tickCount: Int,
        XSteps: Float, currentX: Float
    ) {
        // 绘制竖向网格线
        if (isShowVerticalLines) {
            //if (i > 0 && i + 1 < tickCount) //line
            drawGridLinesVertical(canvas, currentX, plotBottom, currentX, plotTop)
        }
    }


    fun drawClipDataAxisGridlines(canvas: Canvas,
                                  dataAxis: DataLineAxis,
                                  bodyViewport: Viewport,
                                 // 与柱形图不同，无须多弄一个
                                  XSteps:Float = 0.0f,
                                  YSteps:Float = 0.0f,
                                  // 标签轴(X 轴)
                                  axisX:Float = 0.0f,
                                  axisY:Float = 0.0f,
                                  // 数据轴数据刻度总个数
                                  tickCount: Int = dataAxis.axisTickCount,
                                  pos: ChartEnum.AxisLocation = dataAxis.axisLocation,
                                  isPrimaryTick:Boolean = true
    ) {
        val lstDataTick = dataAxis.lstLabels

        var currentX:Float
        var currentY:Float

        // 标签
        var currentTickLabel:Float

        lstDataTick.clear()
        // 绘制
        for (i in 0 until tickCount ) {
            when (pos) {
                ChartEnum.AxisLocation.LEFT, ChartEnum.AxisLocation.RIGHT, ChartEnum.AxisLocation.VERTICAL_CENTER -> {
                    // 依起始数据坐标与数据刻度间距算出上移高度
                    currentY = Math.sub(bodyViewport.bottom, Math.mul(i.toFloat(), YSteps))

                    val isPrimary = isPrimaryTick.ifValue(dataAxis.isPrimaryTick(i),false)
                    // 从左到右的横向网格线
                    renderHorizontalGridLines(canvas, isPrimary, bodyViewport.left, bodyViewport.right, i, tickCount , YSteps, currentY)

                    // 这个有点问题，要处理下，
                    // 隐藏时应当不需要这个，但目前主明细模式下，会有问题，加 了一个都显示不出来
                    // 先省略了
                    // if(!dataAxis.isShowAxisLabels())continue;

                    // 标签
                    currentTickLabel = Math.add(dataAxis.axisMin, Math.mul(i.toFloat(), dataAxis.axisSteps))
                    lstDataTick.add(PlotAxisTick(i, axisX, currentY, currentTickLabel.toString()))
                }
                ChartEnum.AxisLocation.TOP, ChartEnum.AxisLocation.BOTTOM, ChartEnum.AxisLocation.HORIZONTAL_CENTER -> {
                    // 依初超始X坐标与标签间距算出当前刻度的X坐标
                    currentX = Math.add(bodyViewport.left, Math.mul(i.toFloat(), XSteps))

                    // 绘制竖向网格线
                    renderVerticalGridLines(canvas, bodyViewport.top, bodyViewport.bottom, i, tickCount , XSteps, currentX)

                    // if(!dataAxis.isShowAxisLabels())continue;

                    // 画上标签/刻度线
                    currentTickLabel = Math.add(dataAxis.axisMin, i * dataAxis.axisSteps)
                    lstDataTick.add(PlotAxisTick(i, currentX, axisY, currentTickLabel.toString()))
                }
            }
        } // end for

    }

    /**
     * 基本 类型
     */
    fun drawClipCategoryAxisGridlines(canvas: Canvas,
                                      categoryAxis: CategoryLineAxis,
                                      bodyViewport: Viewport,
                                      xCoordFirstTickmarksBegin:Boolean = false,
                                      barCenterStyle:ChartEnum.BarCenterStyle = ChartEnum.BarCenterStyle.TICKMARKS,
                                      j1:Int=0,
                                  // 与柱形图不同，无须多弄一个
                                      XSteps:Float = 0.0f,
                                      YSteps:Float = 0.0f,
                                  // 标签轴(X 轴)
                                      axisX:Float = 0.0f,
                                      axisY:Float = 0.0f,
                                  // 数据轴数据刻度总个数
                                      tickCount: Int = categoryAxis.dataSet.size,
                                      pos: ChartEnum.AxisLocation = categoryAxis.axisLocation
    ) {
        val lstCateTick = categoryAxis.lstLabels

        var currentX: Float
        var currentY: Float

        // 得到标签轴数据集
        val dataSet: List<String> = categoryAxis.dataSet

        var j = j1

        lstCateTick.clear()
        var labelX: Float
        var labelY: Float
        var showTicks = true

        // 绘制
        for (i in 0 until tickCount) {
            when (pos) {
                ChartEnum.AxisLocation.LEFT, ChartEnum.AxisLocation.RIGHT, ChartEnum.AxisLocation.VERTICAL_CENTER -> {
                    // 依起始数据坐标与数据刻度间距算出上移高度
                    //currentY = sub(plotArea.getBottom(), j * YSteps);
                    if (xCoordFirstTickmarksBegin) {
                        currentY = Math.sub(bodyViewport.bottom, Math.mul((j + 1).toFloat(), YSteps))
                    } else {
                        currentY = Math.sub(bodyViewport.bottom, Math.mul(j.toFloat(), YSteps))
                    }

                    // 从左到右的横向网格线
                    renderHorizontalGridLines(canvas, isMajorTickLine = true, bodyViewport.left, bodyViewport.right, i, tickCount, YSteps, currentY)
                    if (!categoryAxis.isShowAxisLabels) continue

                    //mLstCateTick.add(new PlotAxisTick(axisX, currentY, dataSet.get(i)));
                    labelX = axisX
                    labelY = currentY
                    if (xCoordFirstTickmarksBegin && ChartEnum.BarCenterStyle.SPACE == barCenterStyle) {
                        if (i == tickCount - 1) showTicks = false
                        labelY = Math.add(currentY, Math.div(YSteps, 2f))
                    }
                    lstCateTick.add(PlotAxisTick(axisX, currentY, dataSet[i], labelX, labelY, showTicks))
                }
                ChartEnum.AxisLocation.TOP, ChartEnum.AxisLocation.BOTTOM, ChartEnum.AxisLocation.HORIZONTAL_CENTER -> {
                    // 依初超始X坐标与标签间距算出当前刻度的X坐标
                    if (xCoordFirstTickmarksBegin) {
                        currentX = Math.add(bodyViewport.left, Math.mul((j + 1).toFloat(), XSteps))
                    } else {
                        currentX = Math.add(bodyViewport.left, Math.mul(j.toFloat(), XSteps))
                    }

                    // 绘制竖向网格线
                    renderVerticalGridLines(canvas, bodyViewport.top, bodyViewport.bottom, i, tickCount, XSteps, currentX)

                    if (!categoryAxis.isShowAxisLabels) continue

                    labelX = currentX
                    labelY = axisY
                    if (xCoordFirstTickmarksBegin && ChartEnum.BarCenterStyle.SPACE == barCenterStyle) {
                        if (i == tickCount - 1)
                            showTicks = false
                        labelX = Math.sub(currentX, Math.div(XSteps, 2f))
                    }
                    lstCateTick.add(PlotAxisTick(currentX, axisY, dataSet[i], labelX, labelY, showTicks))
                }
            }
            j++
        } // end for
    }

    /**
     * Bar 类型
     */
    fun drawClipCategoryAxisGridlines(canvas: Canvas,
                                      categoryAxis: CategoryLineAxis,
                                      bodyViewport: Viewport,
                                      barCenterStyle:ChartEnum.BarCenterStyle = ChartEnum.BarCenterStyle.TICKMARKS,
                                      // 与柱形图不同，无须多弄一个
                                      XSteps:Float = 0.0f,
                                      YSteps:Float = 0.0f,
                                     // 标签轴(X 轴)
                                      axisX:Float = 0.0f,
                                      axisY:Float = 0.0f,
                                      offset3DX:Float = 0f,
                                      baseOffset3DX:Float = 0f,
                                      baseOffset3DY:Float = 0f,
                                      // 数据轴数据刻度总个数
                                      tickCount: Int = categoryAxis.dataSet.size,
                                      pos: ChartEnum.AxisLocation = categoryAxis.axisLocation
    ) {
        val lstCateTick = categoryAxis.lstLabels

        var currentX: Float
        var currentY: Float

        // 标签
        var currentTickLabel: Float

        // 得到标签轴数据集
        val dataSet: List<String> = categoryAxis.dataSet

        lstCateTick.clear()
        var labelX: Float
        var labelY: Float
        var showTicks = true

        //绘制
        for (i in 0 until tickCount) {
            when (pos) {
                ChartEnum.AxisLocation.LEFT, ChartEnum.AxisLocation.RIGHT, ChartEnum.AxisLocation.VERTICAL_CENTER -> {
                    // 依初超始Y坐标与分类间距算出当前刻度的Y坐标
                    currentY = Math.sub(axisY, Math.mul((i + 1).toFloat(), YSteps))

                    // 从左到右的横向网格线
                    renderHorizontalGridLines(canvas, false, bodyViewport.left, bodyViewport.right, i, tickCount, YSteps, currentY)
                    if (!categoryAxis.isShowAxisLabels) continue
                    labelY = currentY
                    run {
                        currentX = Math.sub(axisX, offset3DX)
                        labelX = currentX
                    }
                    if (ChartEnum.BarCenterStyle.SPACE == barCenterStyle) {
                        //if(i == tickCount - 1)continue;
                        if (i == tickCount - 1) showTicks = false
                        labelY = Math.add(currentY, Math.div(YSteps, 2f))
                    }

                    // 分类
                    lstCateTick.add(PlotAxisTick(currentX, currentY, categoryAxis.dataSet[i], labelX, labelY, showTicks))
                }
                ChartEnum.AxisLocation.TOP, ChartEnum.AxisLocation.BOTTOM, ChartEnum.AxisLocation.HORIZONTAL_CENTER -> {
                    // 依初超始X坐标与分类间距算出当前刻度的X坐标
                    currentX = Math.add(bodyViewport.left, Math.mul((i + 1).toFloat(), XSteps))

                    //绘制竖向网格线
                    renderVerticalGridLines(
                        canvas, bodyViewport.top,  bodyViewport.bottom,
                        i, tickCount, XSteps, currentX
                    )
                    if (!categoryAxis.isShowAxisLabels) continue
                    val currentY2: Float = Math.add(axisY, baseOffset3DY)
                    currentX = Math.sub(currentX, baseOffset3DX)
                    labelX = currentX
                    labelY = currentY2
                    if (ChartEnum.BarCenterStyle.SPACE == barCenterStyle) {
                        if (i == tickCount - 1) {
                            showTicks = false
                        }
                        labelX = Math.sub(currentX, Math.div(XSteps, 2f))
                    }
                    lstCateTick.add(PlotAxisTick(currentX, currentY2, dataSet[i], labelX, labelY, showTicks))
                }
            }
        } //end for

    }

    /**
     * Line 类型
     */
    fun drawClipCategoryAxisGridlines(canvas: Canvas,
                                      categoryAxis: CategoryLineAxis,
                                      bodyViewport: Viewport,
                                      // 与柱形图不同，无须多弄一个
                                      XSteps:Float = 0.0f,
                                      YSteps:Float = 0.0f,
                                      // 标签轴(X 轴)
                                      axisX:Float = 0.0f,
                                      axisY:Float = 0.0f,
                                      // 数据轴数据刻度总个数
                                      tickCount: Int = categoryAxis.dataSet.size,
                                      pos: ChartEnum.AxisLocation = categoryAxis.axisLocation,
                                      isPrimaryTick:Boolean = false
    ) {
        val lstCateTick = categoryAxis.lstLabels

        var currentX: Float
        var currentY: Float

        // 得到标签轴数据集
        val dataSet: List<String> = categoryAxis.dataSet

        lstCateTick.clear()

        //绘制
        for (i in 0 until tickCount) {
            when (pos) {
                ChartEnum.AxisLocation.LEFT, ChartEnum.AxisLocation.RIGHT, ChartEnum.AxisLocation.VERTICAL_CENTER -> {
                    // 依初超始Y坐标与分类间距算出当前刻度的Y坐标
                    currentY = Math.sub(axisY, Math.mul((i + 1).toFloat(), YSteps))

                    // 从左到右的横向网格线
                    renderHorizontalGridLines(canvas, isPrimaryTick, bodyViewport.left, bodyViewport.right, i, tickCount, YSteps, currentY)
                    if (!categoryAxis.isShowAxisLabels) continue

                    // 分类
                    lstCateTick.add(PlotAxisTick(axisX, currentY, categoryAxis.dataSet[i]))
                }

                ChartEnum.AxisLocation.TOP, ChartEnum.AxisLocation.BOTTOM, ChartEnum.AxisLocation.HORIZONTAL_CENTER -> {
                    // 依初超始X坐标与分类间距算出当前刻度的X坐标
                    currentX =
                        Math.add(bodyViewport.left, Math.mul((i + 1).toFloat(), XSteps))

                    //绘制竖向网格线
                    renderVerticalGridLines(canvas, bodyViewport.top, bodyViewport.bottom, i, tickCount, XSteps, currentX)
                    if (!categoryAxis.isShowAxisLabels) continue
                    lstCateTick.add(PlotAxisTick(currentX, axisY, dataSet[i]))
                }
            }
        } //end for
    }

    companion object{
        private const val BLOB_WIDTH = 2
    }
}